using global::GoGameClient.script.global;
using Godot;
using GoGameClient.script.map;
using GoGameClient.script.tool;

namespace GoGameClient.script.role;

public partial class RoleControl : Node2D
{
    [Signal]
    public delegate void OffsetSignalEventHandler(Vector2I vector);

    [Signal]
    public delegate void MoveSignalEventHandler(Vector2I vector);

    //测试
    private bool _isMove;
    private Camera2D _camera2D;
    private Vector2 _cachePosition = new(-999, -999);
    private int _tileWidth;
    private int _tileHeight;
    private int _index;
    private float _speed = 200.0f; // 移动速度，单位为像素/秒  
    private readonly Terrain _terrain = new();
    private Vector2I _targetPosition;
    private string _direction;
    private Model _model;


    public override void _Ready()
    {
        GetNode<Label>("RoleName").Text = UserControl.GetInstance().GetRole().RoleName;
        _model = GetNode<Model>("Model");
        _camera2D = GetNode<Camera2D>("Camera2D");
    }

    public void UpdateCamera2D()
    {
        _camera2D.LimitLeft = 0;
        _camera2D.LimitTop = 0;
        _camera2D.LimitRight = ResourcesControl.Instance().GetCurrentMapInfo().Width;
        _camera2D.LimitBottom = ResourcesControl.Instance().GetCurrentMapInfo().Height;
        _tileWidth = ResourcesControl.Instance().GetCurrentMapInfo().Col;
        _tileHeight = ResourcesControl.Instance().GetCurrentMapInfo().Row;
    }


    public void SetPosition(Vector2I position)
    {
        Position = Vector2Util.MapToPosition(position);
        SendMoveMessage();
        SendPositionMessage();
    }


    public void SetModel(string name)
    {
        _model.SetModel(name);
    }


    public override void _UnhandledInput(InputEvent ievent)
    {
        var isAction = ievent.IsActionPressed("LEFT_CLICK");
        if (!isAction) return;
        _isMove = true;
        _direction = null;
        var terrainAStarGrid2D = ResourcesControl.Instance().GetCurrentAStart();
        var target = (Vector2I)(GetLocalMousePosition() + Position);
        if (terrainAStarGrid2D != null)
        {
            _terrain.AStarGrid2D = terrainAStarGrid2D;
            if (!_terrain.IsMove(Vector2Util.PositionToMap(target)))
            {
                _isMove = false;
                return;
            }

            _terrain.CurrentV = Vector2Util.PositionToMap((Vector2I)Position);
            _terrain.TargetV = Vector2Util.PositionToMap(target);
            _terrain.StartPathRoute();
            _targetPosition = Vector2Util.MapToPosition(_terrain.GetCurrentPosition());
            return;
        }

        _targetPosition = target;
    }


    public override void _Process(double delta)
    {
        if (!_isMove) return;
        Limit();
        SendMoveMessage();
        SendPositionMessage();
        Move(Position, _targetPosition, delta);
    }

    private void SendMoveMessage()
    {
        EmitSignal(SignalName.MoveSignal,
            new Vector2I((int)(Position.X / 20), (int)(Position.Y / 20)));
    }

    private void SetDirection(Vector2 position, Vector2I targetV)
    {
        var direction = Vector2Util.GetDirection(targetV, (Vector2I)position);
        if (direction != null)
        {
            _direction = direction;
        }
    }


    private void Move(Vector2 position, Vector2I targetV, double delta)
    {
        //设置方向
        if (_direction == null)
        {
            SetDirection(position, targetV);
            _model.Move(_direction);
        }

        if (position.DistanceTo(targetV) >= 4)
        {
            Position = position.Lerp(targetV, (float)(delta * _speed / Position.DistanceTo(targetV)));
            return;
        }

        Position = targetV;
        if (_terrain == null)
        {
            _model.Wait(_direction);
            _direction = null;
            _isMove = false;
            EmitSignal(SignalName.MoveSignal, new Vector2I(0, 0));
            return;
        }

        _terrain.UpdateLinePosition();
        var targetPosition = Vector2Util.MapToPosition(_terrain.GetCurrentPosition());
        if (targetPosition == targetV)
        {
            _model.Wait(_direction);
            _direction = null;
            _isMove = false;
            EmitSignal(SignalName.MoveSignal, new Vector2I(0, 0));
            return;
        }

        _direction = null;
        _targetPosition = targetPosition;
    }

    private void SendPositionMessage()
    {
        var tempPosition = (_cachePosition - Position).Abs();
        if (!(tempPosition.X >= _tileWidth) && !(tempPosition.Y >= _tileHeight)) return;
        _cachePosition = Position;
        EmitSignal(SignalName.OffsetSignal,
            new Vector2I((int)(Position.X / _tileWidth), (int)(Position.Y / _tileHeight)));
    }

    private void Limit()
    {
        if (Position.X <= 0)
        {
            Position = Position with { X = 0 };
        }

        if (Position.Y <= 0)
        {
            Position = Position with { Y = 0 };
        }

        if (Position.X > ResourcesControl.Instance().GetCurrentMapInfo().Width)
        {
            Position = Position with { X = ResourcesControl.Instance().GetCurrentMapInfo().Width };
        }

        if (Position.Y > ResourcesControl.Instance().GetCurrentMapInfo().Height)
        {
            Position = Position with { Y = ResourcesControl.Instance().GetCurrentMapInfo().Height };
        }
    }
}